#include "dualmodel.h"

DualModel::DualModel(const QAbstractItemModel *gameModel,
                                     const QAbstractItemModel *armyModel,
                                     QObject *parent) :
    QAbstractListModel(parent)
{
    Q_ASSERT(gameModel && armyModel);
    this->gameModel = gameModel;
    this->armyModel = armyModel;

    // Game model signals

    connect(gameModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
            this, SLOT(game_dataChanged(QModelIndex,QModelIndex)));
    connect(gameModel, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
            this, SLOT(game_headerDataChanged(Qt::Orientation,int,int)));
    connect(gameModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
            this, SLOT(game_rowsAboutToBeInserted(QModelIndex,int,int)));
    connect(gameModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
            this, SLOT(game_rowsAboutToBeRemoved(QModelIndex,int,int)));
    connect(gameModel, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
            this, SLOT(game_rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
    connect(gameModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
            this, SLOT(common_rowsInserted()));
    connect(gameModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
            this, SLOT(common_rowsMoved()));
    connect(gameModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
            this, SLOT(common_rowsRemoved()));
    connect(gameModel, SIGNAL(modelAboutToBeReset()), this, SLOT(common_modelAboutToBeReset()));
    connect(gameModel, SIGNAL(modelReset()), this, SLOT(common_modelReset()));


    // Army model signals

    connect(armyModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
            this, SLOT(army_dataChanged(QModelIndex,QModelIndex)));
    connect(armyModel, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
            this, SLOT(army_rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
    connect(armyModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
            this, SLOT(army_rowsAboutToBeRemoved(QModelIndex,int,int)));
    connect(armyModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
            this, SLOT(army_rowsAboutToBeInserted(QModelIndex,int,int)));
    connect(armyModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
            this, SLOT(common_rowsInserted()));
    connect(armyModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
            this, SLOT(common_rowsMoved()));
    connect(armyModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
            this, SLOT(common_rowsRemoved()));
    connect(armyModel, SIGNAL(modelAboutToBeReset()), this, SLOT(common_modelAboutToBeReset()));
    connect(armyModel, SIGNAL(modelReset()), this, SLOT(common_modelReset()));
}

QVariant DualModel::data(const QModelIndex &index, int role) const {
    if(!index.isValid())
        return QVariant();
    int row = index.row();
    int gameRowCount = gameModel->rowCount();
    if(row >= gameRowCount) {
        row -= gameRowCount;
        return armyModel->data(armyModel->index(row,0), role);
    }
    return gameModel->data(gameModel->index(row,0), role);
}

int DualModel::rowCount (const QModelIndex &parent) const {
    Q_UNUSED(parent)
    return gameModel->rowCount() + armyModel->rowCount();
}

QVariant DualModel::headerData(int section, Qt::Orientation orientation, int role) const {
    return gameModel->headerData(section, orientation, role);
}

void DualModel::game_headerDataChanged(Qt::Orientation orientation, int first, int last) {
    emit headerDataChanged(orientation, first, last);
}

void DualModel::common_modelAboutToBeReset() {
    beginResetModel();
}

void DualModel::common_modelReset() {
    endResetModel();
}

void DualModel::game_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) {
    emit dataChanged(index(topLeft.row()), index(bottomRight.row()));
}

void DualModel::game_rowsAboutToBeInserted(const QModelIndex &parent, int first, int last) {
    Q_UNUSED(parent);
    beginInsertRows(QModelIndex(), first, last);
}

void DualModel::game_rowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart,
                          int sourceEnd, const QModelIndex &destinationParent,
                          int destinationRow) {
    Q_UNUSED(sourceParent);
    Q_UNUSED(destinationParent);
    beginMoveRows(QModelIndex(), sourceStart, sourceEnd, QModelIndex(), destinationRow);
}

void DualModel::game_rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last) {
    Q_UNUSED(parent);
    beginRemoveRows(QModelIndex(), first, last);
}

void DualModel::common_rowsInserted() {
    endInsertRows();
}

void DualModel::common_rowsMoved() {
    endMoveRows();
}

void DualModel::common_rowsRemoved() {
    endRemoveRows();
}

void DualModel::army_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) {
    // Army rows are located after game rows
    int gameRows = gameModel->rowCount();
    emit dataChanged(index(topLeft.row() + gameRows), index(bottomRight.row() + gameRows));
}

void DualModel::army_rowsAboutToBeInserted(const QModelIndex &parent, int first, int last) {
    Q_UNUSED(parent);
    // Army rows are located after game rows
    int gameRows = gameModel->rowCount();
    beginInsertRows(QModelIndex(), first + gameRows, last + gameRows);
}

void DualModel::army_rowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart,
                          int sourceEnd, const QModelIndex &destinationParent,
                          int destinationRow) {
    Q_UNUSED(sourceParent);
    Q_UNUSED(destinationParent);
    // Army rows are located after game rows
    int gameRows = gameModel->rowCount();
    beginMoveRows(QModelIndex(), sourceStart + gameRows, sourceEnd + gameRows,
                            QModelIndex(), destinationRow + gameRows);
}

void DualModel::army_rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last) {
    Q_UNUSED(parent);
    // Army rows are located after game rows
    int gameRows = gameModel->rowCount();

    beginRemoveRows(QModelIndex(), first + gameRows, last + gameRows);
}
